<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI流式聊天接口 - DeepSeek风格</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
        }

        body {
            /* 炫酷的科技感太空背景：蓝紫星云+星空 */
            background:
                    radial-gradient(ellipse at 60% 40%, #3a5eff 0%, #7f53ff 40%, #232946 70%, #0f1021 100%),
                    linear-gradient(120deg, #00eaff55 0%, #7f53ff33 100%),
                    repeating-radial-gradient(circle at 80% 20%, #fff 1px, transparent 2px, transparent 100px),
                    repeating-radial-gradient(circle at 20% 80%, #fff 1px, transparent 2px, transparent 120px);
            background-blend-mode: lighten, screen, normal;
            color: #e0e7ef;
            min-height: 100vh;
            padding: 0;
            position: relative;
            overflow-x: hidden;
        }
        /* 流星动画 */
        .meteor {
            position: absolute;
            width: 2px;
            height: 80px;
            background: linear-gradient(180deg, #fff 0%, #00eaff 100%);
            opacity: 0.7;
            border-radius: 2px;
            filter: blur(0.5px);
            animation: meteor-fall 2.5s linear infinite;
        }
        .meteor.m1 { left: 10%; top: 5%; animation-delay: 0s; }
        .meteor.m2 { left: 30%; top: 10%; animation-delay: 0.8s; }
        .meteor.m3 { left: 60%; top: 2%; animation-delay: 1.2s; }
        .meteor.m4 { left: 80%; top: 15%; animation-delay: 1.7s; }
        .meteor.m5 { left: 50%; top: 8%; animation-delay: 2.1s; }
        @keyframes meteor-fall {
            0% { transform: translateY(0) scaleX(1); opacity: 0.8; }
            80% { opacity: 1; }
            100% { transform: translateY(600px) scaleX(1.2); opacity: 0; }
        }
        /* 激光横线 */
        .laser {
            position: absolute;
            left: 0;
            width: 100vw;
            height: 2px;
            background: linear-gradient(90deg, transparent, #00eaff 60%, #fff 100%, transparent);
            opacity: 0.18;
            filter: blur(1px);
            animation: laser-move 4s linear infinite;
        }
        .laser.l1 { top: 25%; animation-delay: 0s; }
        .laser.l2 { top: 55%; animation-delay: 2s; }
        @keyframes laser-move {
            0% { opacity: 0.18; }
            50% { opacity: 0.35; }
            100% { opacity: 0.18; }
        }
        /* 炫酷发光粒子 */
        .glow-dot {
            position: absolute;
            border-radius: 50%;
            pointer-events: none;
            opacity: 0.7;
            filter: blur(1.5px);
            animation: glow-move 6s linear infinite;
        }
        .glow-dot.d1 { left: 15vw; top: 30vh; width: 18px; height: 18px; background: #00eaff; animation-delay: 0s; }
        .glow-dot.d2 { left: 70vw; top: 18vh; width: 12px; height: 12px; background: #7f53ff; animation-delay: 2s; }
        .glow-dot.d3 { left: 40vw; top: 60vh; width: 10px; height: 10px; background: #fff; animation-delay: 1.2s; }
        .glow-dot.d4 { left: 80vw; top: 80vh; width: 16px; height: 16px; background: #00eaff; animation-delay: 3.5s; }
        .glow-dot.d5 { left: 25vw; top: 80vh; width: 8px; height: 8px; background: #7f53ff; animation-delay: 4.1s; }
        @keyframes glow-move {
            0% { opacity: 0.7; transform: scale(1) translateY(0); }
            50% { opacity: 1; transform: scale(1.2) translateY(-20px); }
            100% { opacity: 0.7; transform: scale(1) translateY(0); }
        }

        .container {
            max-width: 1200px;
            height: 100vh;
            margin: 0 auto;
            display: flex;
            flex-direction: column;
            gap: 0;
            position: relative;
            z-index: 10;
            background: rgba(15, 22, 40, 0.6);
            backdrop-filter: blur(8px);
        }

        header {
            text-align: center;
            padding: 20px 0;
            background: rgba(30, 40, 80, 0.45);
            box-shadow: 0 4px 15px rgba(0, 255, 255, 0.08);
            backdrop-filter: blur(10px);
            position: sticky;
            top: 0;
            z-index: 100;
        }

        h1 {
            font-size: 2.2rem;
            margin-bottom: 5px;
            color: #00eaff;
            text-shadow: 0 0 18px #00eaff, 0 0 32px #1a2980;
            letter-spacing: 1px;
        }

        .subtitle {
            font-size: 1rem;
            opacity: 0.92;
            max-width: 800px;
            margin: 0 auto;
            line-height: 1.6;
            color: #7fdfff;
        }

        .chat-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            padding: 20px;
            overflow: hidden;
        }

        .chat-history {
            flex: 1;
            overflow-y: auto;
            padding: 20px 10px;
            display: flex;
            flex-direction: column;
            gap: 25px;
        }

        .message {
            max-width: 85%;
            padding: 18px 22px;
            border-radius: 18px;
            line-height: 1.6;
            position: relative;
            animation: fadeIn 0.3s ease-out;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        .user-message {
            align-self: flex-end;
            background: linear-gradient(135deg, #00eaff 0%, #1a2980 100%);
            color: #fff;
            border-bottom-right-radius: 5px;
        }

        .ai-message {
            align-self: flex-start;
            background: rgba(30, 40, 80, 0.8);
            border: 1px solid rgba(0, 234, 255, 0.18);
            border-bottom-left-radius: 5px;
        }

        .message-header {
            display: flex;
            align-items: center;
            gap: 12px;
            margin-bottom: 12px;
            font-weight: 600;
        }

        .avatar {
            width: 36px;
            height: 36px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.2rem;
        }

        .user-avatar {
            background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%);
            color: #0f2027;
        }

        .ai-avatar {
            background: linear-gradient(135deg, #00eaff 0%, #1a2980 100%);
            color: #fff;
        }

        .input-area {
            padding: 20px;
            background: rgba(30, 40, 80, 0.45);
            box-shadow: 0 -4px 15px rgba(0, 0, 0, 0.2);
            backdrop-filter: blur(10px);
            border-top: 1px solid rgba(0, 234, 255, 0.18);
        }

        .input-group {
            display: flex;
            gap: 15px;
            max-width: 900px;
            margin: 0 auto;
        }

        input {
            flex: 1;
            padding: 16px 20px;
            border: none;
            border-radius: 12px;
            background: rgba(0, 234, 255, 0.08);
            color: #e0e7ef;
            font-size: 1rem;
            outline: none;
            transition: background 0.3s, box-shadow 0.3s;
        }

        input:focus {
            background: rgba(0, 234, 255, 0.16);
            box-shadow: 0 0 0 2px #00eaff80;
        }

        input::placeholder {
            color: #7fdfff;
        }

        button {
            padding: 16px 30px;
            background: linear-gradient(135deg, #00eaff 60%, #1a2980 100%);
            border: none;
            border-radius: 12px;
            color: #fff;
            font-weight: bold;
            font-size: 1rem;
            cursor: pointer;
            box-shadow: 0 4px 15px #00eaff40;
            letter-spacing: 1px;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 10px;
        }

        button:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 20px #00eaff60;
            background: linear-gradient(135deg, #1a2980 0%, #00eaff 100%);
        }

        button:active {
            transform: translateY(1px);
        }

        .streaming-indicator {
            display: none;
            align-items: center;
            gap: 10px;
            margin-top: 10px;
            color: #00eaff;
            padding: 10px 0;
            justify-content: center;
        }

        .spinner {
            width: 20px;
            height: 20px;
            border: 3px solid rgba(0, 234, 255, 0.18);
            border-radius: 50%;
            border-top-color: #00eaff;
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            to { transform: rotate(360deg); }
        }

        .status {
            padding: 10px;
            border-radius: 8px;
            margin: 10px auto;
            max-width: 900px;
            display: none;
            text-align: center;
        }

        .status.success {
            background: rgba(0, 255, 255, 0.10);
            border: 1px solid rgba(0, 255, 255, 0.18);
            display: block;
        }

        .status.error {
            background: rgba(255, 0, 80, 0.10);
            border: 1px solid rgba(255, 0, 80, 0.18);
            display: block;
        }

        footer {
            text-align: center;
            padding: 15px;
            background: rgba(30, 40, 80, 0.25);
            font-size: 0.9rem;
            opacity: 0.85;
            color: #7fdfff;
        }

        @media (max-width: 768px) {
            .container {
                padding: 0;
            }

            .chat-container {
                padding: 10px;
            }

            .input-group {
                flex-direction: column;
            }

            button {
                width: 100%;
                justify-content: center;
            }

            .message {
                max-width: 95%;
            }
        }
    </style>
</head>
<body>
<!-- 太空动效元素 -->
<div class="meteor m1"></div>
<div class="meteor m2"></div>
<div class="meteor m3"></div>
<div class="meteor m4"></div>
<div class="meteor m5"></div>
<div class="laser l1"></div>
<div class="laser l2"></div>
<div class="glow-dot d1"></div>
<div class="glow-dot d2"></div>
<div class="glow-dot d3"></div>
<div class="glow-dot d4"></div>
<div class="glow-dot d5"></div>

<div class="container">
    <header>
        <h1><i class="fas fa-comments"></i> AI流式聊天接口</h1>
        <p class="subtitle">基于Spring Boot流式接口的DeepSeek风格聊天界面</p>
    </header>

    <div class="chat-container">
        <div class="chat-history" id="chatHistory">
            <!-- AI欢迎消息 -->
            <div class="message ai-message">
                <div class="message-header">
                    <div class="avatar ai-avatar">
                        <i class="fas fa-robot"></i>
                    </div>
                    <span>AI助手</span>
                </div>
                <div class="message-content">
                    您好！我是AI助手，基于Spring Boot流式接口构建。我可以实时生成回答，请随时向我提问！
                    <br><br>
                    <strong>示例问题：</strong>
                    <ul style="margin-top: 10px; padding-left: 20px;">
                        <li>量子计算的基本原理是什么？</li>
                        <li>请写一篇关于太空探索的短文</li>
                        <li>解释神经网络如何工作</li>
                    </ul>
                </div>
            </div>
        </div>

        <div class="input-area">
            <div class="input-group">
                <input type="text" id="promptInput" placeholder="输入您的问题...">
                <button onclick="sendMessage()">
                    <i class="fas fa-paper-plane"></i> 发送消息
                </button>
            </div>
            <div class="streaming-indicator" id="streamIndicator">
                <div class="spinner"></div>
                <span>AI正在思考中...</span>
            </div>
            <div class="status" id="status"></div>
        </div>
    </div>

    <footer>
        <p>Spring AI流式接口演示 | 后端接口路径: /ai/chatStream | DeepSeek风格优化</p>
    </footer>
</div>

<script>
    // 添加新消息到聊天历史
    function addMessage(role, content) {
        const chatHistory = document.getElementById('chatHistory');
        const messageDiv = document.createElement('div');

        if (role === 'user') {
            messageDiv.className = 'message user-message';
            messageDiv.innerHTML = `
                <div class="message-header">
                    <div class="avatar user-avatar">
                        <i class="fas fa-user"></i>
                    </div>
                    <span>您</span>
                </div>
                <div class="message-content">${content}</div>
            `;
        } else {
            messageDiv.className = 'message ai-message';
            messageDiv.innerHTML = `
                <div class="message-header">
                    <div class="avatar ai-avatar">
                        <i class="fas fa-robot"></i>
                    </div>
                    <span>AI助手</span>
                </div>
                <div class="message-content">${content}</div>
            `;
        }

        chatHistory.appendChild(messageDiv);
        // 滚动到底部
        chatHistory.scrollTop = chatHistory.scrollHeight;

        return messageDiv;
    }

    // 发送消息
    async function sendMessage() {
        const input = document.getElementById('promptInput');
        const prompt = input.value.trim();
        const status = document.getElementById('status');
        const indicator = document.getElementById('streamIndicator');
        const sendBtn = document.querySelector('button');

        if (!prompt) {
            status.className = 'status error';
            status.innerHTML = '请输入问题';
            return;
        }

        // 添加用户消息
        addMessage('user', prompt);

        // 创建AI消息容器
        const aiMessageDiv = addMessage('ai', '<i class="fas fa-spinner fa-spin"></i> 思考中...');
        const aiContent = aiMessageDiv.querySelector('.message-content');

        // 禁用输入和按钮
        input.disabled = true;
        sendBtn.disabled = true;
        indicator.style.display = 'flex';
        status.className = '';

        try {
            // 创建EventSource连接
            const eventSource = new EventSource(`/ai/chatStream?prompt=${encodeURIComponent(prompt)}`);

            // 清空内容并准备接收流式数据
            aiContent.innerHTML = '';

            eventSource.onmessage = (event) => {
                // 追加新内容到AI消息区域
                aiContent.innerHTML += event.data;

                // 自动滚动到底部
                document.querySelector('.chat-history').scrollTop = document.querySelector('.chat-history').scrollHeight;
            };

            eventSource.onerror = (error) => {
                eventSource.close();
                indicator.style.display = 'none';

                if (error.eventPhase === EventSource.CLOSED) {
                    status.className = 'status success';
                    status.innerHTML = `流式传输完成 - ${new Date().toLocaleTimeString()}`;
                } else {
                    status.className = 'status error';
                    status.innerHTML = '流式传输错误';
                    console.error('EventSource error:', error);
                }

                // 重新启用输入和按钮
                input.disabled = false;
                sendBtn.disabled = false;
                input.value = '';
                input.focus();
            };
        } catch (error) {
            aiContent.innerHTML = '<span style="color:#ff6b6b">请求失败，请稍后重试</span>';
            status.className = 'status error';
            status.innerHTML = `错误: ${error.message}`;

            // 重新启用输入和按钮
            input.disabled = false;
            sendBtn.disabled = false;
            indicator.style.display = 'none';
        }
    }

    // 添加回车键支持
    document.getElementById('promptInput').addEventListener('keypress', (e) => {
        if (e.key === 'Enter') sendMessage();
    });

    // 页面加载后自动聚焦输入框
    window.onload = function() {
        document.getElementById('promptInput').focus();
    };
</script>
</body>
</html>